<?php
namespace App\Service\BMR;
use App\Model\FoodModel;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class BMR_Food1 {
    protected $url = 'https://myingyang.911cha.com/';
    protected static $keys;
    protected $agentArry=[
            //PC端的UserAgent
        "safari 5.1 – MAC"=>"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
        "safari 5.1 – Windows"=>"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
        "Firefox 38esr"=>"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
        "IE 11"=>"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
        "IE 9.0"=>"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0",
        "IE 8.0"=>"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
        "IE 7.0"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
        "IE 6.0"=>"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
        "Firefox 4.0.1 – MAC"=>"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
        "Firefox 4.0.1 – Windows"=>"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
        "Opera 11.11 – MAC"=>"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
        "Opera 11.11 – Windows"=>"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
        "Chrome 17.0 – MAC"=>"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
        "傲游（Maxthon）"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
        "腾讯TT"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
        "世界之窗（The World） 2.x"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
        "世界之窗（The World） 3.x"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
        "360浏览器"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
        "搜狗浏览器 1.x"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
        "Avant"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
        "Green Browser"=>"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
    ];

    /**标签正则
     * $param string $tag 标签名
     * @param bool $isSingle 是否单标签
     * @return string
     */
    public function tagPatter($tag, $isSingle = false)
    {
        return !$isSingle
            ? "/<{$tag}(.+?)>(.+?)<\/{$tag}>/ius"  //开始结束标签
            : "<{$tag}(.+?)>";                      //单标签
    }

    /*
     * 获取标题数组
     * @return array
     */
    public static function keys()
    {
        if (!static::$keys) {
            static::$keys = config('bmr.food.keys');
        }
        return static::$keys;
    }

    /**获取标题的英文标识
     * @return array
     */
    public static function getKeysEn()
    {
        return array_column(static::keys(), 'en');
    }

    /**获取标题中文标识
     * @return array
     */
    public static function getKeysZh()
    {
        return array_column(static::keys(), 'zh');
    }

    /**
     * 以标题英文键作为key，中文作为value
     * @reutrn array
     * [
     *    'category' => '类别'
     * ]
     */
    public static function getKeysEnZh()
    {
        return array_combine(static::getKeysEn(), static::getKeysZh());
    }
    /**
     * 以标题中文键作为key，英文作为value
     * @reutrn array
     * [
     *    '类别' => 'category'
     * ]
     */
    public static function getKeysZhEn()
    {
        return array_combine(static::getKeysZh(), static::getKeysEn());
    }

    protected function getUserAgent()
    {
        return $this->agentArry[array_rand($this->agentArry)];
    }

    protected function getClient()
    {
        return new Client([
            'timeout'  => 2.0,
            'verify' => false,
            'headers'=> [
                'User-Agent'    => $this->getUserAgent()
            ]
        ]);
    }

    /**表单字段
     * @param $inputs
     * @return array
     */
    protected function form($inputs) {
        return [
            'form_params' => $inputs
        ];
    }

    protected function parseHref($href) {
        return trim($this->url, '/').'/'.trim(trim($href, '.'), '/');
    }

    protected function htmlToText($html) {
        return strip_tags($html);
    }

    /**获取多个关键词 如 搜索胡萝卜，可能有 红胡萝卜，黄胡萝卜等
     * @param $name
     */
    protected function getAllKeyword($name) {
        $return = [];
        $response = $this->getClient()->request('POST', $this->url, $this->form([
            'q' => trim($name)
        ]));
        $html = $response->getBody()->getContents();
        //查找ul
        $ulPattern = '/<ul\s+class="txtlist\s+arrow">(.+?)<\/ul>/';
        preg_match_all($ulPattern, $html, $ulList);
        if (isset($ulList[0][0])) {
            //查找多个li
            $ulList = $ulList[0][0];
            $liPattern = '/<li>(.+?)<\/li>/';
            preg_match_all($liPattern, $ulList, $liList);
            if (isset($liList[0])) {
                $liList = $liList[0];
                //查找a标签下的链接，以及关键字
                $aPattern = '/<a\s+href="(.+?)"(.+?)>(.+?)<\/a>/';
                foreach($liList as $li) {
                    preg_match_all($aPattern, $li, $a);
                    if (isset($a[1][0]) && isset($a[3][0]))
                        $return[] = [
                        'href' => $this->parseHref($a[1][0]), //链接
                        'text' => $this->htmlToText($a[3][0]) //关键字
                    ];
                }
            }
        }

        return $return;
    }

    /** 根据链接获取营养
     * @param $url
     * @return
     * [
     *  '营养英文名' => 营养克数
     *  ...
     * ]
     */
    protected function getNutrition($url)
    {
        $return = [];
        $html = $this->getClient()->request('GET', $url)->getBody()->getContents();
        //查找第一个table
        preg_match_all($this->tagPatter('table'), $html, $result);
        if (!isset($result[2][0])) {
            return $return;
        }
        $table   = $result[2][0];
        //查找tr标签
        preg_match_all($this->tagPatter('tr'), $table, $trResult);
        if (!isset($trResult[0][0])) {
            return $return;
        }
        $trList = $trResult[0];
        $aPattern = $this->tagPatter('a');
        $weightPattern = $this->tagPatter('td');
        //英文标题
        $keys = static::getKeysZhEn();
        //初始化每个tr标签内容
        foreach($trList as $line => $tr) {
            //跳过第一行标题
            if ($line == 0) {
                continue;
            }
            //查找td标签
            preg_match_all($aPattern, $tr, $aResult);
            if (!isset($aResult[2][0])) {
                continue;
            }
            //重量
            preg_match_all($weightPattern, $tr, $weightResult);
            if (!isset($weightResult[1][0])) {
                continue;
            }

            $name = trim($aResult[2][0]);
            $weight = (float)strip_tags($weightResult[0][0]);

            //数据库不存在这个字段 跳过
            if (!isset($keys[$name])) {
                continue;
            }
            $return[$keys[$name]] = number_format($weight, 2, '.', '');
        }
        return $return;
    }

    /**采集某个食物
     * @param $name
     */
    public function gather($name)
    {
        try {
            $keywordList = $this->getAllKeyword($name);
            $inserts = [];
            $now = (string)Carbon::now();
            foreach($keywordList as $keyword) {
                $nutritions = $this->getNutrition($keyword['href']);
                if (empty($nutritions)) {
                    continue;
                }
                $inserts[] = array_merge([
                    'category' => $keyword['text'],
                    'created_at'=> $now
                ], $nutritions);
            }
        } catch(\Exception $e) {
            Log::info($e->getFile().'--'.$e->getLine().'--'.$e->getMessage());
            return false;
        }

        //查到存数据表中
        return !empty($inserts) ? FoodModel::insert($inserts) : false;
    }
}


